package utils;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.Stack;

import probability.GaussianDistribution;

import basics.DenseMatrix;
import basics.DenseVector;
import basics.Matrix;
import basics.Vector;

public class Printer {

	public static String toString(GaussianDistribution[][] p) {
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < p.length; i++) {
			for (int j = 0; j < p[0].length; j++) {
				sb.append(p[i][j].toString());
			}
		}
		return sb.toString();
	}

	public static void printStream(String str, Set s) {
		printStream(System.out, s);
	}

	public static void print(String str, Set s) {
		Object[] l = s.toArray();
		print(str, l);
	}

	private static void print(String str, Object[] l) {
		String append = ",";
		innerPrint(str);
		for (int i = 0; i < l.length; i++) {
			if (i == l.length - 1)
				append = "\n";
			innerPrint(l[i].toString() + append);
		}
	}

	public static void print(String str, double[] dd) {
		String append = ",";
		innerPrint(str);
		for (int i = 0; i < dd.length; i++) {
			if (i == dd.length - 1)
				append = "\n";
			innerPrint(dd[i] + append);
		}
	}

	public static void print(String str, int[] dd) {
		String append = ",";
		innerPrint(str);
		for (int i = 0; i < dd.length; i++) {
			if (i == dd.length - 1)
				append = "\n";
			innerPrint(dd[i] + append);
		}
	}

	public static void print(String str, List l) {
		String append = ",";
		innerPrint(str);
		for (int i = 0; i < l.size(); i++) {
			if (i == l.size() - 1)
				append = "\n";
			innerPrint(l.get(i).toString() + append);
		}
	}

	public static void printStream(PrintStream out, Set s) {
		for (Object o : s) {
			out.println(o.toString());
		}
	}

	public static void printStream(List s) {
		printStream(System.out, s);
	}

	public static void printStream(PrintStream out, List s) {
		for (Object o : s) {
			out.println(o.toString());
		}
	}

	public static boolean contains(String v, String[] q) {
		for (String s : q) {
			if (s.equals(v)) {
				return true;
			}
		}
		return false;
	}

	public static boolean contains(String v, Set s) {
		return s.contains(v);
	}

	public static boolean contains(String v, ArrayList o) {
		return o.contains(v);
	}

	public static boolean isInStack(Set cv, Stack s) {
		for (Object item : cv) {
			if (!s.contains(item)) {
				return false;
			}
		}

		return true;
	}

	public static int indexOf(String[] args, String key) {
		int idx = -1;
		for (int i = 0; i < args.length; i++) {
			if (args[idx].equalsIgnoreCase(key)) {
				idx = i;
				break;
			}
		}
		return idx;
	}

	public static void print(String filePath, String str) {
		try {
			print(new PrintStream(filePath), str);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}

	public static void print(PrintStream ps, String str) {
		ps.print(str);
	}

	public static void addAll(Collection list1, Collection list2) {
		for (Object o : list2) {
			if (!list1.contains(o)) {
				list1.add(o);
			}
		}
	}

	public static void removeIntersection(Collection hs, Collection list) {
		for (Object o : list) {
			if (hs.contains(o)) {
				hs.remove(o);
			}
		}
	}

	private static HashMap<String, StringBuilder> _log = new HashMap<String, StringBuilder>();

	public static void writeLog(String filePath, String key) {
		print(filePath, _log.get(key).toString());
	}

	public static void printlntToLog(String key, String str) {
		appendToFile(key, str);
		if (!_log.containsKey(key)) {
			_log.put(key, new StringBuilder());
		}
		_log.get(key).append(str + "\n");
	}

	public static void print(String str) {
		str = str + "------------------------------\n";
		innerPrint(str);
	}

	private static void innerPrint(String str) {
		//System.out.println(str);
		appendToFile("", str);
		appendToFile("latest", str);
	}

	private static HashMap<String, BufferedWriter> writer = new HashMap<String, BufferedWriter>();

	public static void appendToFile(final String file, String str) {
		try {
			if (writer.get(file) == null) {
				String path = file;
				if (file == null || file.length() == 0) {
					Calendar cal = Calendar.getInstance();
					path = cal.get(Calendar.YEAR) + "_" + cal.get(Calendar.MONTH) + "_"
							+ cal.get(Calendar.DAY_OF_MONTH) + "_" + cal.get(Calendar.HOUR_OF_DAY) + "_"
							+ cal.get(Calendar.MINUTE) + "_" + cal.get(Calendar.SECOND);
				}
				writer.put(file, new BufferedWriter(new FileWriter("./log/" + path)));
			}
			writer.get(file).append(str);
			writer.get(file).flush();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	public static void print(Matrix u) {
		print(System.out, u);
	}

	public static void print(PrintStream ps, Matrix u) {
		for (int i = 0; i < u.length(1); i++) {
			for (int j = 0; j < u.length(2); j++) {
				ps.print(u.get(i, j) + ",");
			}
			ps.println();
		}
	}

	public static void print(PrintStream ps, Vector u) {
		for (int i = 0; i < u.length(1); i++) {
			ps.print(u.get(i) + ",");
		}
		ps.println();
	}
}
